package cn.smvc.task.common.service;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletContext;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.WebApplicationContextUtils;

import cn.smvc.common.Constant;
import cn.smvc.common.cache.CacheManager;
import cn.smvc.common.utils.CronSequenceGenerator;
import cn.smvc.common.utils.DateUtil;
import cn.smvc.common.utils.EmailUtils;
import cn.smvc.common.utils.HttpRespons;
import cn.smvc.common.utils.HttpUtils;
import cn.smvc.common.utils.StringUtils;
import cn.smvc.task.entity.TTimedTask;
import cn.smvc.task.entity.TTimedTaskContact;
import cn.smvc.task.entity.TTimedTaskLog;
import cn.smvc.task.service.TTimedTaskContactService;
import cn.smvc.task.service.TTimedTaskLogService;
import cn.smvc.task.service.TTimedTaskService;
import cn.smvc.wechat.util.CommonUtil;

public class TimedTaskService extends Thread {

	Logger logger = Logger.getLogger(TimedTaskService.class);

	private TTimedTask tTimedTask;
	
	private String cacheTaskId;
	
	private CronSequenceGenerator cronSequenceGenerator;
	
	private ServletContext servletContext;
	
	private HttpUtils httpUtils = new HttpUtils();
	
	private static String[] EXE_RESULT = {"正常","异常","超时"};
	
	@Autowired
	private TTimedTaskService tTimedTaskService;
	@Autowired
	private TTimedTaskLogService tTimedTaskLogService;
	@Autowired
	private TTimedTaskContactService tTimedTaskContactService;

	public TimedTaskService() {
		super();
	}

	public TimedTaskService(TTimedTask tTimedTask, ServletContext servletContext) {
		this.setCacheTaskId(Constant.CACHE_TASK_PREFIX  + tTimedTask.getId());
		this.tTimedTask = tTimedTask;
		cronSequenceGenerator = new CronSequenceGenerator(tTimedTask.getTaskCron());
		
		this.servletContext = servletContext;
		WebApplicationContextUtils.getWebApplicationContext(servletContext)
		.getAutowireCapableBeanFactory().autowireBean(this);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void run() {
		try {
			while (true) {
				//通过缓存任务ID，从缓存中获取改任务信息
				tTimedTask = (TTimedTask) CacheManager.get(cacheTaskId);
				/*
				 * 检查终止
				 * 	判断任务运行状态，
				 * 	若关闭则跳出循环。
				 */
				if("F".equals(tTimedTask.getRunFlag())) {
					System.out.println("TimedTaskService--->" + tTimedTask.getId() + "   结束！！！！！！！！！！！！！");
					break;
				}
				
				/*
				 * 检验是否执行任务
				 */
				Date currDate = new Date();
				Date nextDate;
				long nextExecuteTimestamp = 0L;
				if(StringUtils.isNotEmpty(this.tTimedTask.getNextExecuteTimestamp())) {
					nextExecuteTimestamp = Long.parseLong(this.tTimedTask.getNextExecuteTimestamp());
				} else {
					nextDate = this.cronSequenceGenerator.next(currDate);
					nextExecuteTimestamp = nextDate.getTime();
					
					//保存下次执行时间
					this.tTimedTask.setNextExecuteTimestamp(nextDate.getTime() + "");
					this.tTimedTask.setNextExecuteDatetime(DateUtil.formatDateTime(nextDate));
					tTimedTaskService.updateNextExecuteDatetime(
							this.tTimedTask.getNextExecuteTimestamp(), 
							this.tTimedTask.getNextExecuteDatetime(), 
							this.tTimedTask.getId());
				}
				
				if(nextExecuteTimestamp >= currDate.getTime()) {
					if(nextExecuteTimestamp - currDate.getTime() <= 1000) {
						//------------------------执行调度任务-------------------------------------
						TTimedTaskLog taskLog = new TTimedTaskLog();
						taskLog.setTaskId(tTimedTask.getId());
						taskLog.setTaskName(tTimedTask.getTaskName());
						taskLog.setTaskGroup(tTimedTask.getTaskGroup());
						Date start = new Date();
						taskLog.setStartTime(start);
						taskLog.setCreateTime(start);
						
						Date end = null;
						try {
							if(tTimedTask.getTaskClassType() == 0) {
								Class clazz=Class.forName(tTimedTask.getTaskClass());
								Constructor c=clazz.getConstructor(ServletContext.class);//获取有参构造
								Object tt = c.newInstance(this.servletContext);
		//						Constructor c=clazz.getConstructor();//获取无参构造
		//						Object tt = c.newInstance();
		
		//						Method init = clazz.getDeclaredMethod("init");
								Method execute = clazz.getDeclaredMethod("execute");
		//						init.invoke(tt, this.servletContext);
							
								execute.invoke(tt);
							} else if(tTimedTask.getTaskClassType() == 1) {
								if(tTimedTask.getTaskClass().startsWith("http://")) {
									
									HttpRespons response = httpUtils.sendGet(tTimedTask.getTaskClass());
									System.out.println("response==>" + response);
									if(response.getCode() != 200) {
										throw new RuntimeException();
									}
								} else {
									throw new RuntimeException();
								}
								
							}
							
							
							end = new Date();
							taskLog.setEndTime(end);
							taskLog.setExeResult(0);//执行结果：0正常，1异常，3超时
							int exeTimeLong = new BigDecimal(end.getTime() - start.getTime()).intValue();
							taskLog.setExeTimeLong(exeTimeLong);
							//TODO 处理判断是否超时
							
							
						} catch (Exception e) {
							logger.error("执行任务 " + tTimedTask.getId() + " 失败！", e);
							end = new Date();
							taskLog.setEndTime(end);
							taskLog.setExeResult(1);//执行结果：0正常，1异常，3超时
							taskLog.setExeTimeLong(new BigDecimal(end.getTime() - start.getTime()).intValue());
							//TODO 发送通知信息
							List<TTimedTaskContact> contactList = tTimedTaskContactService.findByTaskId(tTimedTask.getId());
							sendEmail(contactList, taskLog);
							
							sendWeChat(contactList, taskLog);
							
						} finally {
							//保存日志
							tTimedTaskLogService.save(taskLog);
						}
						
						//------------------------更新调度任务信息中的执行时间（上次执行时间，下次执行时间）----------------------
						this.tTimedTask.setLastExecuteTimestamp(nextExecuteTimestamp + "");
						this.tTimedTask.setLastExecuteDatetime(DateUtil.formatDateTime(new Date(nextExecuteTimestamp)));
						nextDate = this.cronSequenceGenerator.next(new Date());
						this.tTimedTask.setNextExecuteTimestamp(nextDate.getTime() + "");
						this.tTimedTask.setNextExecuteDatetime(DateUtil.formatDateTime(nextDate));
						tTimedTaskService.updateNextAndLastExecuteDatetime(
								this.tTimedTask.getNextExecuteTimestamp(), 
								this.tTimedTask.getNextExecuteDatetime(), 
								this.tTimedTask.getLastExecuteTimestamp(), 
								this.tTimedTask.getLastExecuteDatetime(), 
								this.tTimedTask.getId());
						
					}
				} else {
					/* 下次执行时间小于当前时间，说明这个下次执行时间失效，不可能再执行，要重新更新赋值*/
					nextDate = this.cronSequenceGenerator.next(new Date());
					this.tTimedTask.setNextExecuteTimestamp(nextDate.getTime() + "");
					this.tTimedTask.setNextExecuteDatetime(DateUtil.formatDateTime(nextDate));
					tTimedTaskService.updateNextExecuteDatetime(
							this.tTimedTask.getNextExecuteTimestamp(), 
							this.tTimedTask.getNextExecuteDatetime(), 
							this.tTimedTask.getId());
				}
				
				
				// 巡检间隔
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}
		} catch (Exception e) {
			logger.error("执行任务 " + tTimedTask.getId() + " 失败！", e);
		}
	}
	/**
	 * 发送邮件
	 * @param contactList
	 * @param taskLog
	 */
	public void sendEmail(List<TTimedTaskContact> contactList, TTimedTaskLog taskLog) {
		if(contactList != null && contactList.size() > 0) {
			String eamilAddrs = "";//邮箱地址，多个用 ; 连接
			for(TTimedTaskContact c : contactList) {
				if(StringUtils.isNotEmpty(c.getEmail())) {
					eamilAddrs += c.getEmail() + ";";
				}
			}
			if(StringUtils.isNotEmpty(eamilAddrs)) {
				eamilAddrs = eamilAddrs.substring(0, eamilAddrs.length() - 1);
				String subject = DateUtil.formatDateTime(taskLog.getCreateTime()) 
						+ "——TaskID:" + tTimedTask.getId() + " 调度任务执行异常";
				try {
					EmailUtils.sendTextEmail(eamilAddrs, subject, subject);
				} catch (Exception e1) {
					logger.error("邮件发送异常！！！", e1);
				}
			}
		}
	}
	/**
	 * 发送微信推送
	 * @param contactList
	 * @param taskLog
	 */
	public void sendWeChat(List<TTimedTaskContact> contactList, TTimedTaskLog taskLog) {
		/* http 调用发送接口
		String urlString = "http://i.yanjr.cn/app/send/msg";
		Map<String, String> params = new HashMap<String, String>();
		if(contactList != null && contactList.size() > 0) {
			for(TTimedTaskContact c : contactList) {
				if(StringUtils.isNotEmpty(c.getWechat())) {
					try {
						params.put("method", "sentTask");
						params.put("taskId", c.getTaskId());
						params.put("taskGroup", c.getTaskGroup());
						params.put("createTime", taskLog.getCreateTime().getTime() + "");
						params.put("type", EXE_RESULT[taskLog.getExeResult()]);//执行结果：0正常，1异常，3超时
						params.put("openId", c.getWechat());
						httpUtils.sendGet(urlString, params);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			
		}
		*/
		/* 直接调用发送类  */
		if(contactList != null && contactList.size() > 0) {
			for(TTimedTaskContact c : contactList) {
				if(StringUtils.isNotEmpty(c.getWechat())) {
					CommonUtil.sendTaskTempMsg(
							c.getWechat(), 
							c.getTaskId(), 
							c.getTaskGroup(), 
							taskLog.getCreateTime().getTime() + "", 
							EXE_RESULT[taskLog.getExeResult()], 
							CommonUtil.getToken().getAccessToken());
				}
			}
			
		}
	}

	public TTimedTask gettTimedTask() {
		return tTimedTask;
	}

	public void settTimedTask(TTimedTask tTimedTask) {
		this.tTimedTask = tTimedTask;
	}

	public String getCacheTaskId() {
		return cacheTaskId;
	}

	public void setCacheTaskId(String cacheTaskId) {
		this.cacheTaskId = cacheTaskId;
	}

}
